﻿using System;
using System.Collections.Generic;
using System.Linq;
using CarsRegistrationService.Managers.Interfaces;
using CarsRegistrationService.Models.ViewModel;
using System.Data.Objects;
using CarsRegistrationService.Models;
using CarsRegistrationService.Models.LightDataModel;
using System.Transactions;

namespace CarsRegistrationService.Managers
{
    public class ExpertManager : BaseLinqManager, IExpertManager
    {
        public LightExpert Expert { get; set; }

        private IDictionary<int, string> dbErrorMessage;
        private const string DIRECTORY_NAME = "C:\\RequestsData";

        public ExpertManager()
        {
            this.dbErrorMessage = new Dictionary<int, string>
                                      {
                { -1, "Пользователь с таким логином уже существует" }
            };
        }

        public bool IsUserDataCorrect(string login, string passHash)
        {
            var user = LinqContext.Users.FirstOrDefault(u => u.Login == login);
            if (user == null)
            {
                return false;
            }
            var passHash2 = user.PasswordHash;
            bool result = MD5Verify(passHash, passHash2);
            if (result && !user.IsAdmin)
            {
                Expert expert = LinqContext.Experts.First(e => e.User.Login == login);
                this.Expert = new LightExpert(expert);
            }
            return result;
        }

        public string Registration(string login, string password,
                                   string firstName, string lastName,
                                   string middleName, string passportSeries,
                                   string passportNumber)
        {
            try
            {
                if (LinqContext.Users.Any(u => u.Login == login))
                {
                    return this.dbErrorMessage[-1];
                }
                using (var ts = new TransactionScope())
                {

                    var userID = Guid.NewGuid();
                    var user = new User
                    {
                        ID = userID,
                        Login = login,
                        PasswordHash = MD5Encode(password)
                    };
                    LinqContext.Users.AddObject(user);

                    var passport = LinqContext.PersonPassports.FirstOrDefault(
                        p => p.Number == passportNumber && p.Series == passportSeries);
                    Guid passportID;
                    if (passport == null)
                    {
                        passportID = Guid.NewGuid();
                        passport = new PersonPassport
                        {
                            ID = passportID,
                            DateBirthday = DateTime.Now,
                            FirstName = firstName,
                            LastName = lastName,
                            MiddleName = middleName,
                            Number = passportNumber,
                            Series = passportSeries
                        };
                        LinqContext.PersonPassports.AddObject(passport);
                    }
                    else
                    {
                        passportID = passport.ID;
                    }

                    var expertID = Guid.NewGuid();
                    var expert = new Expert
                    {
                        ID = expertID,
                        UserID = userID,
                        PersonPassportID = passportID
                    };
                    LinqContext.Experts.AddObject(expert);

                    LinqContext.SaveChanges();

                    ts.Complete();

                    return null;
                }
            }
            catch (Exception)
            {
                return "Неизвестная ошибка при регистрации эксперта";
            }
        }

        public List<RequestViewModel> GetRequests()
        {
            var result = LinqContext.Requests.Where(r => r.IsReady && !r.IsProcessed)
                .Select(
                    r => new RequestViewModel
                             {
                                 Date = r.DateCreated,
                                 ID = r.ID,
                                 OwnerFullName = r.OwnerName,
                                 VehicleNumber = r.VehicleNumber
                             }).OrderBy(r => r.Date).ToList();

            return result;
        }

        public void DeleteRequest(Guid requestID)
        {
            Request request = LinqContext.Requests.FirstOrDefault(r => r.ID == requestID);
            if (request != null)
            {
                using (var ts = new TransactionScope())
                {
                    var images = LinqContext.Images.Where(i => i.RequestID == requestID);
                    foreach (var image in images)
                    {
                        System.IO.File.Delete(image.FilePath);
                        LinqContext.DeleteObject(image);
                    }
                    string requestDirectory = System.IO.Path.Combine(DIRECTORY_NAME, requestID.ToString());
                    System.IO.Directory.Delete(requestDirectory);
                    LinqContext.Requests.DeleteObject(request);
                    LinqContext.SaveChanges();
                    ts.Complete();
                }
            }
        }

        public LightRequest GetLightRequest(Guid requestID)
        {
            var request = LinqContext.Requests.FirstOrDefault(r => r.ID == requestID);
            if (request == null)
            {
                return null;
            }
            var images = LinqContext.Images.Where(i => i.RequestID == requestID).Select(i => i.FilePath).ToList();
            var lightRequest = new LightRequest
                                   {
                                       ID = requestID,
                                       Images = images
                                   };
            return lightRequest;
        }

        public void ProcessRequest(Guid requestID, LightPersonPassport lPersonPassport,
            LightVehiclePassport lVehiclePassport)
        {
            using (var ts = new TransactionScope())
            {
                var request = LinqContext.Requests.First(r => r.ID == requestID);
                var personPassport = this.CreatePersonPassport(lPersonPassport);
                var vehiclePassport = this.CreateVehiclePassport(lVehiclePassport);
                var owner = LinqContext.Owners.FirstOrDefault(o => o.PersonPassportID == personPassport.ID) ??
                            new Owner
                                {
                                    ID = Guid.NewGuid(),
                                    PersonPassportID = personPassport.ID
                                };
                request.OwnerID = owner.ID;
                request.VehiclePassportID = vehiclePassport.ID;

                LinqContext.PersonPassports.AddObject(personPassport);
                LinqContext.Owners.AddObject(owner);
                LinqContext.VehiclePassports.AddObject(vehiclePassport);

                request.IsProcessed = true;
                LinqContext.SaveChanges();

                ts.Complete();
            }
        }

        private PersonPassport CreatePersonPassport(LightPersonPassport lPersonPassport)
        {
            var passport = LinqContext.PersonPassports.FirstOrDefault(
                pp => pp.Series == lPersonPassport.Series &&
                pp.Number == lPersonPassport.Number);
            if (passport == null)
            {
                passport = new PersonPassport
                {
                    ID = Guid.NewGuid(),
                    FirstName = lPersonPassport.FirstName,
                    LastName = lPersonPassport.LastName,
                    MiddleName = lPersonPassport.MiddleName,
                    Series = lPersonPassport.Series,
                    Number = lPersonPassport.Number
                };
            }
            return passport;
        }
        private VehiclePassport CreateVehiclePassport(LightVehiclePassport lVehiclePassport)
        {
            var vehiclePassport = LinqContext.VehiclePassports.FirstOrDefault(
                vp => vp.VIN == lVehiclePassport.VIN);
            if (vehiclePassport == null)
            {
                vehiclePassport = new VehiclePassport
                {
                    ID = Guid.NewGuid(),
                    VIN = lVehiclePassport.VIN,
                    Series = lVehiclePassport.CarSeries,
                    CarDate = lVehiclePassport.CarDate,
                    EngineModel = lVehiclePassport.EngineModel,
                    EngineNumber = lVehiclePassport.EngineNumber,
                    Brand = lVehiclePassport.Brand,
                    Model = lVehiclePassport.Model,
                    Category = lVehiclePassport.Category,
                    ChassisNumber = lVehiclePassport.ChassisNumber,
                    BodyNumber = lVehiclePassport.BodyNumber,
                    BodyColor = lVehiclePassport.BodyColor,
                    EnginePower = lVehiclePassport.EnginePower,
                    EngineWorkingVolume = lVehiclePassport.EngineWorkingVolume,
                    EngineType = lVehiclePassport.EngineType,
                    MaxMass = lVehiclePassport.MaxMass,
                    CountryExport = lVehiclePassport.CountryExport,
                    CustomsRestrictions = lVehiclePassport.CustomsRestrictions,
                    Manufacturer = lVehiclePassport.Manufacturer
                };
            }
            return vehiclePassport;
        }
    }
}